package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.Destination;
import cn.wolfcode.wolf2w.domain.Strategy;
import cn.wolfcode.wolf2w.domain.StrategyCatalog;
import cn.wolfcode.wolf2w.exception.LogicException;
import cn.wolfcode.wolf2w.query.StrategyCatalogQuery;
import cn.wolfcode.wolf2w.repository.StrategyCatalogRepository;
import cn.wolfcode.wolf2w.repository.StrategyRepository;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.IStrategyCatalogService;
import cn.wolfcode.wolf2w.vo.CatalogVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 攻略分类业务层的实现类
 */
@Service
public class StrategyCatalogServiceImpl implements IStrategyCatalogService {

    //  注入StrategyCatalogRepository持久层接口
    @Autowired
    private StrategyCatalogRepository strategyCatalogRepository;

    //  注入StrategyRepository持久层接口
    @Autowired
    private StrategyRepository strategyRepository;

    //  注入MongoTemplate服务
    @Autowired
    private MongoTemplate mongoTemplate;

    //  注入IDestinationService业务层接口
    @Autowired
    private IDestinationService destinationService;

    //  插入单个方法
    @Override
    public void insert(StrategyCatalog strategyCatalog) {

        //  id自动生成，手动设置为空
        strategyCatalog.setId(null);

        if (strategyCatalog.getSequence() != null) {
            Destination destination = destinationService.selectById(strategyCatalog.getDestId());
            strategyCatalog.setDestName(destination.getName());
            //  调用持久层接口的save方法执行插入单个攻略分类对象
            strategyCatalogRepository.save(strategyCatalog);
        } else {
            throw new LogicException("序号不能为空");
        }
    }

    //  删除单个方法
    @Override
    public void deleteById(String id) {

        //  调用持久层接口的deleteById方法执行删除单个攻略分类对象
        strategyCatalogRepository.deleteById(id);
    }

    //  修改单个方法
    @Override
    public void updateById(StrategyCatalog strategyCatalog) {

        //  mongodb的save操作是全量更新，更新单个数据时，其他数据会被清空
        //  因此我们做修改操作时，需要先查询传过来的对象再设置需要修改的参数值

        //  调用本类的查询单个的方法，传入前端的strategyCatalog对象的id进行查询
        Destination destination = destinationService.selectById(strategyCatalog.getDestId());

        //  通过查询出来的destination对象
        //  获取它的name并设置到strategyCatalog中
        strategyCatalog.setDestName(destination.getName());

        //  调用持久层接口的save方法执行修改单个攻略分类对象
        strategyCatalogRepository.save(strategyCatalog);
    }

    //  查询单个方法
    @Override
    public StrategyCatalog selectById(String id) {

        //  调用持久层接口的findById方法执行查询单个攻略分类对象
        return strategyCatalogRepository.findById(id).orElse(null);
    }

    //  查询所有方法
    @Override
    public List<StrategyCatalog> selectAll() {

        //  调用持久层接口的findAll方法执行查询所有攻略分类对象
        return strategyCatalogRepository.findAll();
    }

    //  分页方法
    @Override
    public Page<StrategyCatalog> query(StrategyCatalogQuery qo) {

        //  查询对象
        Query query = new Query();

        //  调用mongodb服务中的count方法
        //  传入上面的查询对象和StrategyCatalog的字节码对象
        //  返回一个满足条件的总记录数
        long totalCount = mongoTemplate.count(query, StrategyCatalog.class);

        //  若查询出来的总记录数为零时
        if (totalCount == 0) {

            //  直接返回一个空集合
            return Page.empty();
        }

        //  调用Pageable的of方法
        //  传入qo对象的当前页，qo对象的当前页显示的最大记录数，排序的顺序，通过_id来排序
        Pageable pageRequest = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.ASC, "_id");

        //  把限制条件加入到查询对象中
        query.with(pageRequest);

        //  调用mongodb服务中的find方法
        //  传入上面的查询对象和StrategyCatalog的字节码对象
        //  返回一个满足条件的攻略分类对象的集合数据
        List<StrategyCatalog> strategyCatalogs = mongoTemplate.find(query, StrategyCatalog.class);

        //  返回一个PageImpl的集合
        //  传入一个满足条件的攻略分类对象的集合数据对象
        //  传入限制条件
        //  返回一个满足条件的总记录数
        return new PageImpl<>(strategyCatalogs, pageRequest, totalCount);
    }

    //  分类下拉框
    @Override
    public List<CatalogVo> groupList() {

        TypedAggregation<StrategyCatalog> agg = Aggregation.newAggregation(StrategyCatalog.class,
                Aggregation.group("destName").
                        push("name").as("names").
                        push("id").as("ids")
        );
        AggregationResults<Map> result = mongoTemplate.aggregate(agg,Map.class);
        List<Map> datas = result.getMappedResults();

        //  显示数据集合
        List<CatalogVo> catalogVoList = new ArrayList<>();

        //  循环遍历
        for (Map data : datas) {

            //  创建catalogVo对象
            CatalogVo catalogVo = new CatalogVo();

            //  获取分组集合中的_id
            String id = data.get("_id").toString();
            //  设置到catalogVo对象中
            catalogVo.setDestName(id);

            //  再创建一个攻略分类集合
            List<StrategyCatalog> strategyCatalogList = new ArrayList<>();

            //  把攻略名字和id都放入集合中
            List<Object> names = (List<Object>) data.get("names");
            List<Object> ids = (List<Object>) data.get("ids");

            //  循环攻略名字的集合
            for (int i = 0; i < names.size(); i++) {
                //  创建攻略分类对象
                StrategyCatalog strategyCatalog = new StrategyCatalog();
                //  循环设置进去
                strategyCatalog.setDestName(names.get(i).toString());
                strategyCatalog.setDestId(ids.get(i).toString());
                //  再添加到攻略分类集合
                strategyCatalogList.add(strategyCatalog);
            }
            //  将攻略分类集合设置到catalogVo对象中
            catalogVo.setCatalog(strategyCatalogList);
            //  将catalogVo对象设置到创建的显示数据集合中
            catalogVoList.add(catalogVo);
        }

        return catalogVoList;
    }

    //  攻略概况-攻略分类与攻略概况明细
    @Override
    public List<StrategyCatalog> queryDestId(String destId) {

        //  根据目的地id查询所有的攻略分类
        List<StrategyCatalog> strategyCatalogList = strategyCatalogRepository.findByDestId(destId);

        //  遍历攻略分类集合
        for (StrategyCatalog strategyCatalog : strategyCatalogList) {
            //  查找拥有相同攻略分类的攻略明细
            List<Strategy> strategieList = strategyRepository.findByCatalogId(strategyCatalog.getId());
            //  设置到攻略分类中
            strategyCatalog.setStrategies(strategieList);
        }

        //  返回
        return strategyCatalogList;
    }


}
